package edu.arizona.mindseye.swing;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;

import edu.arizona.mindseye.Annotation;
import edu.arizona.mindseye.VideoModel;
import edu.arizona.mindseye.event.Event;
import edu.arizona.mindseye.event.EventListener;
import edu.arizona.mindseye.event.EventManager;
import edu.arizona.mindseye.event.enums.EventType;
import edu.arizona.mindseye.event.enums.Parameter;

public class AnnotationPanel extends JPanel {

	private JButton _humans;
	private JButton _mark;
	
	private JButton _clear;
	private JButton _save;

	private JList _list;
	private DefaultListModel _listModel;

	private String _movieName;
	private int    _humanCount;
	private VideoModel _model;
	
	private Object[] _activities = null;
	
	public AnnotationPanel() { 
		super();
		
		setLayout(new GridBagLayout());
		setMinimumSize(new Dimension(200, 500));
		
		addComponents();
		addListeners();
	}
	
	private void addComponents() {
		_humans = new JButton("Human Count");
		_mark = new JButton("Break");
		
		_listModel = new DefaultListModel();
		_list = new JList(_listModel);
		_list.setCellRenderer(new ListCellRenderer() {
			JTextArea _textArea = new JTextArea();;
			
			@Override
			public Component getListCellRendererComponent(JList list,
					Object value, int index, boolean isSelected, boolean cellHasFocus) {
				
				_textArea.setLineWrap( true );
				_textArea.setEditable( false );
				_textArea.setFont( UIManager.getLookAndFeelDefaults().getFont("Label.font"));
				_textArea.setWrapStyleWord( true );				
				
				_textArea.setText(value.toString());
				return _textArea;
			} 
		});

		_clear = new JButton("Clear");
		_save = new JButton("Save");
		
		JPanel top = new JPanel();
		top.setLayout(new FlowLayout());
		top.add(_humans);
		top.add(_mark);
		add(top, GBC.makeGBC(0, 0, GridBagConstraints.BOTH, 1, 0));
		
		add(_list, GBC.makeGBC(0, 1, GridBagConstraints.BOTH, 1, 1));
		
		JPanel bottom = new JPanel();
		bottom.setLayout(new FlowLayout());
		bottom.add(_clear);
		bottom.add(_save);
		add(bottom, GBC.makeGBC(0, 2, GridBagConstraints.BOTH, 1, 0));
		
	}
	
	private void addListeners() { 
		_humans.addActionListener(new ActionListener() { 
			public void actionPerformed(ActionEvent e) { 
				// TODO: pop up a JOptionPane to enter the number of humans
				// in this video.
				String question = "How many humans are in the movie performing the activity?";
				String title = "Human Count";
				
				boolean badResponse = true;
				while (badResponse) { 
					String result = JOptionPane.showInputDialog(null, question, title, JOptionPane.QUESTION_MESSAGE);
					if (result == null || "".equals(result.trim())) 
						return;
					
					try { 
						_humanCount = Integer.parseInt(result);
						badResponse = false;
					} catch (Exception exception) { 
						JOptionPane.showMessageDialog(null, "Please enter a number!");
					}
				}
				
				_mark.setEnabled(true);
				_listModel.removeAllElements();
			}
		});
		
		_mark.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO: create a new MovieComponent and add it to 
				// the list.
				
				
				// First find the max where the previous break started.
				int min = 0;
				for (int i = 0; i < _listModel.getSize(); ++i) { 
					min = Math.max(min, (((Annotation) _listModel.get(i)).max()));
				}
				
				int max = _model.getIndex();
				if (max == min) { 
					JOptionPane.showMessageDialog(null, "Change the frame index before inserting a break");
					return;
				}
				
				Annotation mc = new Annotation(1, min, max);

				// Determine what the activities are ....
				for (int i = 0; i < _humanCount; ++i) { 
					String question = "What was human " + i + " doing?";
					String title = "Human Action";
					String activity = (String) JOptionPane.showInputDialog(null, question, title, JOptionPane.QUESTION_MESSAGE, 
							null, _activities, _activities[0]);
					
					if (activity == null)
						return;
					
					mc.add(activity);
				}
				
				_listModel.addElement(mc);
			}			
		});
		
		_clear.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				_listModel.removeAllElements();
			} 
		});
		
		_save.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				List<Annotation> breaks = new ArrayList<Annotation>();
				for (int i = 0; i < _listModel.getSize(); ++i) { 
					breaks.add((Annotation) _listModel.get(i));
				}
				
				Event event = new Event(EventType.ANNOTATIONS);
				event.addParameter(Parameter.name, _movieName);
				event.addParameter(Parameter.annotation, breaks);
				EventManager.inst().dispatch(event);
			} 
		});
		
		// ---- Below here are the internal events that get passed around.
		EventManager.inst().register(EventType.MOVIE_LOADED, new EventListener() {
			@Override
			public void onEvent(Event e) {
				_movieName = (String) e.getValue(Parameter.name);
				_model = (VideoModel) e.getValue(Parameter.model);
				
				_mark.setEnabled(false);
				_listModel.clear();
			} 
		});
		
		EventManager.inst().register(EventType.BEHAVIORS, new EventListener() {
			@Override
			public void onEvent(Event e) {
				List<String> behaviors = (List<String>) e.getValue(Parameter.behaviors);
				_activities = behaviors.toArray();
			} 
		});
	}
}
